<?php
/**
 * Created by PhpStorm.
 * User: jocky
 * Date: 17/08/2017
 * Time: 02:38
 */

namespace console\controllers;

use Codeception\Util\Template;
use common\models\ar\CrontabLists;
use common\models\ar\HistoryCrontabInfo;
use common\models\ar\OrderHistory;
use common\models\ar\TemplatesDetail;
use common\models\ar\UserTrade;
use common\models\MoneyDao;
use common\models\Sms;
use yii\console\Controller;

set_time_limit(0);

/**
 * 从期权系统中获取orders并写入cta中
 *
 * Class PositionsController
 * @package yii\console\controllers
 */
class OrdersController extends Controller
{
    private $crontabID = 2;
    private $pageSize = 100;

    public function actionIndex()
    {
        $time = time();

        $obj = new HistoryCrontabInfo();
        $obj->attributes = [
            'crontab_id' => $this->crontabID,
            'time_start' => $time,
            'time_end' => 0,
            'status' => 0,
            'remark' => ''
        ];
        $obj->save();

        $crontabObj = CrontabLists::findOne($this->crontabID);
        $crontabObj->latest_id = $obj->id;
        $crontabObj->save();

        //如果有未完成的本类处理任务，则本次不执行
        $unfinishedObj = HistoryCrontabInfo::find()->where(['crontab_id' => $this->crontabID, 'status' => 1])->one();
        if ($unfinishedObj) {
            $obj->status = 3;
            $obj->remark = 'have unfinished task';
            $obj->save();
//            Sms::send('18917510869', 8, "异常：定时任务ID为" . $this->crontabID);
//            return 1;
        }

        //本次开始执行查询的起始时间和结束时间
        $from = $crontabObj->latest_success_operate_time + 1;//从下一秒开始执行
        $to = $time - 60;//统计到当前时间点前一分钟

        $from_str = date('Y-m-d H:i:s', $from);
        $to_str = date('Y-m-d H:i:s', $to);

        //开始执行
        $obj->status = 1;
        $obj->save();

        //获取历史交易
        $this->getHistoryOrders($from_str, $to_str);
        //获取资金变更
        $this->getHistoryMoney($from_str, $to_str);

        $obj->status = 2;
        $obj->time_end = time();
        $obj->save();

        $crontabObj->latest_success_operate_time = $to;
        $crontabObj->save();

        return 0;
    }

    /**
     * 统计某个范围
     *
     * @param $from
     * @param $to
     * @return int
     */
    public function actionRange($from, $to)
    {
        $from = date("Y-m-d H:i:s", strtotime($from));
        $to = date("Y-m-d H:i:s", strtotime($to));

        //获取历史交易
        $this->getHistoryOrders($from, $to);
        //获取资金变更
        $this->getHistoryMoney($from, $to);

        return 0;
    }

    /**
     * 获取用户历史交易
     *
     * @param $from
     * @param $to
     * @return bool
     */
    private function getHistoryOrders($from, $to)
    {
        $time = time();
        $db = \Yii::$app->db_options;
        $sql_count = "SELECT COUNT(1) FROM `orderchange` a ";
        $sql_lists = "SELECT 
                        a.`tradeID`,
                        a.`orderID`,
                        a.`tradeCost`,
                        a.`Volume` volume,
                        a.`time`,
                        a.`price`,
                        b.`userID`,
                        b.`instrumentid` contractID,
                        b.`direction`,
                        d.`product` name,
                        d.`number`
                      FROM `orderchange` a 
        ";

        $sql_join = "LEFT JOIN `orders` b ON b.`orderID` = a.`orderID` 
                     LEFT JOIN `user` c ON c.`userID` = b.`userID` 
                     LEFT JOIN `instrument` d ON d.`number` = b.`instrumentid` 
        ";
        $sql_where = "WHERE a.`time` >= '" . $from . "' AND a.`time` <= '" . $to . "' AND c.`agentID` > 0 ";
        $total = $db->createCommand($sql_count . $sql_join . $sql_where)->queryScalar();

        if ($total == 0) {
            return true;
        }

        //用IGNORE是为了避免上一次由于一些问题导致只插部分数据后，下次执行时重复插入导致主键冲突问题
        $sql = "INSERT IGNORE INTO `order_history` (
                    `tradeID`,
                    `orderID`,
                    `uid`,
                    `contractID`,
                    `contractName`,
                    `direction`,
                    `volume`,
                    `time`,
                    `price`,
                    `trade_cost_my`,
                    `trade_cost`,
                    `level_1_uid`,
                    `level_1_trade_cost`,
                    `level_1_bind_uid`,
                    `level_1_return_flag`,
                    `level_2_uid`,
                    `level_2_trade_cost`,
                    `level_2_bind_uid`,
                    `level_2_return_flag`,
                    `level_3_uid`,
                    `level_3_trade_cost`,
                    `level_3_bind_uid`,
                    `level_3_return_flag`,
                    `level_4_uid`,
                    `level_4_trade_cost`,
                    `level_4_bind_uid`,
                    `level_4_return_flag`,
                    `create_time`
            ) VALUES (
                    :tradeID,
                    :orderID,
                    :uid,
                    :contractID,
                    :contractName,
                    :direction,
                    :volume,
                    :time,
                    :price,
                    :trade_cost_my,
                    :trade_cost,
                    :level_1_uid,
                    :level_1_trade_cost,
                    :level_1_bind_uid,
                    :level_1_return_flag,
                    :level_2_uid,
                    :level_2_trade_cost,
                    :level_2_bind_uid,
                    :level_2_return_flag,
                    :level_3_uid,
                    :level_3_trade_cost,
                    :level_3_bind_uid,
                    :level_3_return_flag,
                    :level_4_uid,
                    :level_4_trade_cost,
                    :level_4_bind_uid,
                    :level_4_return_flag,
                    :create_time
            )
        ";
        $command = \Yii::$app->db->createCommand($sql);

        $pageNo = 1;
        $pageTotal = ceil($total / $this->pageSize);
        while ($pageNo <= $pageTotal) {
            $sql_limit = "LIMIT " . ($pageNo - 1) * $this->pageSize . "," . $this->pageSize;
            $history = $db->createCommand($sql_lists . $sql_join . $sql_where . $sql_limit)->queryAll();
            $pageNo++;

            foreach ($history as $v) {
                $tmp = UserTrade::findOne($v['userID']);
                if (!$tmp || $tmp->template_id == 0) {
                    continue;
                }

                $templateID = $tmp->template_id;
                $uidLinks = $tmp->uid_links;

                //我的成本
                $tmp = TemplatesDetail::find()
                    ->where([
                        'template_id' => $templateID,
                        'product' => $v['name']
                    ])
                    ->asArray()
                    ->one();
                $tradeCostMy = $v['direction'] == 1 ? $tmp['trade_cost_open'] : $tmp['trade_cost_close'];

                //各级代理手续费和绑定的返现账户
                $sql = "
                    SELECT 
                      a.`uid`,
                      a.`level`,
                      a.`bind_user_trade`,
                      a.`trade_cost_return_flag` return_flag,
                      b.`trade_cost_open`,
                      b.`trade_cost_close` 
                    FROM 
                      `user` a 
                    LEFT JOIN `templates_detail` b ON b.`template_id` = a.`template_id` AND b.`product` = :product_id
                    WHERE a.`uid` IN (" . $uidLinks . ")
                ";
                $tmp = \Yii::$app->db->createCommand($sql);
                $tmp->bindValues([
                    ':product_id' => $v['name']
                ]);
                $lists = $tmp->queryAll();

                $tmpLevel = [];
                foreach ($lists as $val) {
                    $tmpLevel[$val['level']] = [
                        'uid' => $val['uid'],
                        'bind_user_trade' => $val['bind_user_trade'],
                        'return_flag' => $val['return_flag'] == 0 ? -3 : 0,
                        'trade_cost' => $v['direction'] == 1 ? $val['trade_cost_open'] : $val['trade_cost_close']
                    ];
                }

                $bind = [
                    ':tradeID' => $v['tradeID'],
                    ':orderID' => $v['orderID'],
                    ':uid' => $v['userID'],
                    ':contractID' => $v['contractID'],
                    ':contractName' => $v['name'],
                    ':direction' => $v['direction'],
                    ':volume' => $v['volume'],
                    ':time' => strtotime($v['time']),
                    ':price' => $v['price'],
                    ':trade_cost_my' => $tradeCostMy,
                    ':trade_cost' => $v['tradeCost'],
                    ':level_1_uid' => $tmpLevel[1]['uid'],
                    ':level_1_trade_cost' => $tmpLevel[1]['trade_cost'],
                    ':level_1_bind_uid' => $tmpLevel[1]['bind_user_trade'],
                    ':level_1_return_flag' => $tmpLevel[1]['return_flag'],
                    ':level_2_uid' => $tmpLevel[2]['uid'],
                    ':level_2_trade_cost' => $tmpLevel[2]['trade_cost'],
                    ':level_2_bind_uid' => $tmpLevel[2]['bind_user_trade'],
                    ':level_2_return_flag' => $tmpLevel[2]['return_flag'],
                    ':level_3_uid' => $tmpLevel[3]['uid'],
                    ':level_3_trade_cost' => $tmpLevel[3]['trade_cost'],
                    ':level_3_bind_uid' => $tmpLevel[3]['bind_user_trade'],
                    ':level_3_return_flag' => $tmpLevel[3]['return_flag'],
                    ':level_4_uid' => $tmpLevel[4]['uid'],
                    ':level_4_trade_cost' => $tmpLevel[4]['trade_cost'],
                    ':level_4_bind_uid' => $tmpLevel[4]['bind_user_trade'],
                    ':level_4_return_flag' => $tmpLevel[4]['return_flag'],
                    ':create_time' => $time
                ];

                $bool = $command->bindValues($bind)->execute();
                unset($bind);
                if (!$bool) {
                    continue;
                }

                //手续费返现
                $this->tradeCostReturn($v['tradeID']);
            }
        }

        return true;
    }

    /**
     * 获取用户资金变更
     *
     * @param $from
     * @param $to
     * @return bool
     */
    private function getHistoryMoney($from, $to)
    {
        $time = time();
        $db = \Yii::$app->db_options;
        $sql_count = "SELECT COUNT(1) FROM `user_money_changerecord` a ";
        $sql_lists = "SELECT 
                        a.`id`,
                        a.`userID`,
                        a.`changeMoney`,
                        a.`changeTime`,
                        a.`changeDesc`,
                        a.`type`
                      FROM 
                        `user_money_changerecord` a
        ";

        $sql_where = "WHERE a.`changeTime` >= '" . $from . "'  AND a.`changeTime` <= '" . $to . "' ";
        $total = $db->createCommand($sql_count . $sql_where)->queryScalar();

        if ($total == 0) {
            return true;
        }

        $pageNo = 1;
        $pageTotal = ceil($total / $this->pageSize);
        while ($pageNo <= $pageTotal) {
            $sql_limit = "LIMIT " . ($pageNo - 1) * $this->pageSize . "," . $this->pageSize;
            $history = $db->createCommand($sql_lists . $sql_where . $sql_limit)->queryAll();
            $pageNo++;

            $record = [];
            foreach ($history as $v) {
                $type = (int)$v['type'];

                if ($type != 4) {
                    //非交易盈亏类，有明确的正负
                    $money = abs($v['changeMoney']);

                    switch ((int)$v['type']) {
                        case 3://手续费
                        case 8://出金
                        case 16://通道费
                            $money = -$money;
                    }
                } else {
                    //交易盈亏，有正有负
                    $money = $v['changeMoney'];
                }

                $record[$v['id']] = "
                    (
                        " . $v['userID'] . ",
                        " . $money . ",
                        " . strtotime($v['changeTime']) . ",
                        " . $v['type'] . ",
                        " . $v['id'] . ",
                        " . $time . ",
                        'crontab | " . $v['changeDesc'] . "',
                        ''
                    )
                ";
            }

            $transaction = \Yii::$app->db->beginTransaction();
            try {
                //插入
                $sql = "INSERT IGNORE INTO `money_change` (
                            `uid`,
                            `money`,
                            `time`,
                            `direction`,
                            `money_change_id`,
                            `create_time`,
                            `remark`,
                            `response`
                        ) VALUES " . implode(',', $record) . "
                ";
                \Yii::$app->db->createCommand($sql)->execute();

                $transaction->commit();
            } catch (\Exception $e) {
                $transaction->rollBack();
                return false;
            }
        }

        return true;
    }

    /**
     * 返现对应的历史记录
     *
     * @param $tradeID
     */
    private function tradeCostReturn($tradeID)
    {
        $time = time();
        $obj = OrderHistory::findOne($tradeID);
        if (!$obj || $obj->return_operate_flag != 0) {
            //非0状态不需要处理
            return;
        }
        $obj->return_operate_flag = 1;//标记为已处理
        $obj->save();

        //各级返现
        for ($i = 2; $i <= 4; $i++) {
            $bindUID = "level_" . $i . "_bind_uid";
            $flag = "level_" . $i . "_return_flag";
            if (!$obj->$bindUID) {
                $obj->$flag = -1;
                $obj->save();
                continue;
            }

            if ($i == 4) {
                $tradeCostSub = "trade_cost_my";
            } else {
                $tradeCostSub = "level_" . ($i + 1) . "_trade_cost";
            }
            $tradeCostMy = "level_" . $i . "_trade_cost";
            $return = ($obj->$tradeCostSub - $obj->$tradeCostMy) * $obj->volume;

            //非正常返现
            if ($return < 0) {
                $obj->$flag = -2;
                $obj->save();
                continue;
            }

            //没有返现，但是要将状态改为已处理
            if ($return == 0) {
                $obj->$flag = 2;
                $obj->save();
                continue;
            }

            //发送中
            $obj->$flag = 1;
            $obj->save();
            $bool = MoneyDao::inOut(0, $obj->$bindUID, 15, $return, $time, 2, '', '', '手续费返现');
            if (!$bool) {
                $code = 3;
            } else {
                $code = 2;
            }

            $obj->$flag = $code;
            $obj->save();
        }
    }
}